package com.stone.framework.message;

import java.util.Optional;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import io.swagger.annotations.ApiModelProperty;

/**
 * 分页请求报文
 * 
 * @author whocares
 * @date 2020/03/28
 */
public class PageReqMessage<T extends SortableBody> extends ReqMessage<T> {

    private static final long serialVersionUID = 6819070717505731609L;

    @ApiModelProperty(value = "當前頁數", required = true)
    @NotNull(message = "[pageNo] {title.notNull}")
    @Min(value = 1, message = "[pageNo] {title.min} 1")
    private Integer pageNo;

    @ApiModelProperty(value = "每頁記錄數", required = true)
    @NotNull(message = "[pageSize] {title.notNull}")
    @Min(value = 1, message = "[pageSize] {title.min} 1")
    private Integer pageSize;

    @ApiModelProperty(value = "正序/倒序")
    @Pattern(regexp = "(ASC|DESC)", message = "[direction] must be 'ASC|DESC'")
    private String direction = "DESC";

    /**
     * use for json
     */
    @Deprecated
    public PageReqMessage() {}

    protected PageReqMessage(T body, Integer pageNo, Integer pageSize) {
        super(body);
        this.pageNo = pageNo;
        this.pageSize = pageSize;
    }

    /**
     * for client-side
     * 
     * @param <T>
     * @param body
     * @param pageNo
     * @param pageSize
     * @return
     */
    public static <T extends SortableBody> PageReqMessage<T> build(T body, Integer pageNo, Integer pageSize) {
        PageReqMessage<T> message = new PageReqMessage<>(body, pageNo, pageSize);
        return message;
    }

    /**
     * for server-side
     * 
     * @param sort
     * @return
     */
    public Pageable buildPage(Sort sort) {
        return PageRequest.of(this.pageNo - 1, this.pageSize, sort);
    }

    /**
     * jpa page for server-side<br>
     * 
     * @return {@link Pageable}
     */
    public Pageable buildPageable() {
        return PageRequest.of(this.pageNo - 1, this.pageSize,
            Direction.fromOptionalString(this.direction).orElse(Direction.DESC),
            Optional.ofNullable(this.getBody().getOrderBy()).orElse("createDate"));
    }

    /**
     * mybatis page for server-side<br>
     * 
     * @return {@link Page}
     */
    public <E> Page<E> buildPage() {
        return new Page<E>(this.pageNo, this.pageSize)
            .addOrder("ASC".equalsIgnoreCase(this.direction) ? OrderItem.asc(this.getBody().getUnderScoreCaseOrderBy())
                : OrderItem.desc(this.getBody().getUnderScoreCaseOrderBy()));
    }

    /**
     * use for swagger
     * 
     * @return
     */
    public Integer getPageNo() {
        return pageNo;
    }

    /**
     * use for json
     * 
     * @param pageNo
     */
    @Deprecated
    public void setPageNo(Integer pageNo) {
        this.pageNo = pageNo;
    }

    /**
     * use for swagger
     * 
     * @return
     */
    public Integer getPageSize() {
        return pageSize;
    }

    /**
     * use for json
     * 
     * @param pageSize
     */
    @Deprecated
    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    /**
     * use for swagger
     * 
     * @return
     */
    public String getDirection() {
        return direction;
    }

    /**
     * use for json
     * 
     * @param direction
     */
    @Deprecated
    public void setDirection(String direction) {
        this.direction = direction;
    }

}
